#include <string.h>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

#if 0
int add(int x, int y)
{
    return x + y;
}

double add(double x, double y)
{
    return x + y;
}

char add(char x, char y)
{
    return x + y;
}

string add(string x, string y)
{
    return x + y;
}
#endif

//根据参数类型将模板参数列表中的T推导到对应的类型
//T---->int
//T---->double
template <typename T>
T add(T x, T y)
{
    cout << "T add(T, T)" << endl;
    return x + y;
}

template <typename T>
T add(T x, T y, T z)
{
    cout << "T add(T, T, T)" << endl;
    return x + y + z;
}

//总结：
//1、普通函数优先于函数模板进行执行
//2、函数模板可以与普通函数之间形成函数重载
//3、函数模板与函数模板之间也是可以进行重载

//将这个过程称为实例化，也就是从抽象的模板类型推导为具体的类型
//将模板类型实例化为了具体类型
//       实例化的过程
//函数模板----->模板函数（其实就是个普通函数）
#if 0
int add(int x, int y)
{
    cout << "int add(int, int)" << endl;
    return x + y;
}
#endif

//模板的特化
//分类：全特化，偏特化（部分特化）
//全特化：将模板参数全部以特殊版本的形式展示出来
//偏特化（部分特化）：将模板参数中的部分参数进行特化
//函数模板只支持全特化，不支持偏特化
template <>
const char *add<const char *>(const char *px, const char *py)
{
    cout << "const char *add(const char *, cosnt char *)" << endl;
    size_t len = strlen(px) + strlen(py) + 1;
    char *pstr = new char[len]();
    strcpy(pstr, px);
    strcat(pstr, py);

    return pstr;
}

void test()
{
    int ia = 3, ib = 4, ic = 5;
    char ca = 'a', cb = 1;
    double da = 1.1, db = 3.4;
    string s1("hello"), s2("wangdao");

    const char *pstr1 = "hello";
    const char *pstr2 = ",world";

    cout << "add(ia, ib) = " << add(ia, ib) << endl;//隐式实例化
    cout << "add(ia, ib) = " << add<int>(ia, ib) << endl;//显示实例化
    cout << "add(ca, cb) = " << add(ca, cb) << endl;
    cout << "add(da, db) = " << add(da, db) << endl;
    cout << "add(s1, s2) = " << add(s1, s2) << endl;

    cout << "add(ia, ib, ic) = " << add(ia, ib, ic) << endl;
    /* cout << "add(ia, db) = " << add(ia, db) << endl;//error */

    cout << "add(pstr1, pstr2) = " << add(pstr1, pstr2) << endl;
}

int main(int argc, char *argv[])
{
    test();
    return 0;
}

